package com.kgc.goods.goodsservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kgc.goods.entity.Goods;
import com.kgc.goods.goodsservice.mapper.GoodsMapper;
import com.kgc.goods.service.GoodsService;
import com.kgc.goods.util.RedisUtil;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.UUID;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author CQW
 * @since 2020-10-05
 */
@Service
@Component
public class GoodsServiceImpl implements GoodsService {

    @Resource
    GoodsMapper goodsMapper;
    @Resource
    RedisUtil redisUtil;
    @Override
    public List<Goods> selectAll(Integer district) {
        List<Goods> goodsList;
        if (district!=-1){
            goodsList=goodsMapper.selectList(new QueryWrapper<Goods>().eq("district",district));
        }else {
            goodsList=goodsMapper.selectList(null);
        }
        return goodsList;
    }

    @Override
    public Goods selectById(Integer id) {
        Goods goods=null;
        Jedis jedis = redisUtil.getJedis();
        String key= "goods:"+id;
        String goodJson = jedis.get(key);
        if (goodJson!=null){
            //解决缓存穿透
            if (goodJson.equals("empty")){
                return null;
            }
            //从redis中查询数据
            goods= JSON.parseObject(goodJson,Goods.class);
            jedis.close();
        }else {
            //使用nx分布式锁，避免缓存击穿
            String skuLockKey="goodId"+id;
            String skuLockValue= UUID.randomUUID().toString();
            String lockKey=jedis.set(skuLockKey,skuLockValue,"NX","PX",60*1000);
            if (lockKey.equals("OK")){
                //从数据库查询
                goods=goodsMapper.selectById(id);
                //解决缓存穿透雪崩
                if (goods!=null){
//                    保存到redis
                    String jsonString = JSON.toJSONString(goods);
                    //有效期随机，防止缓存雪崩
                    Random random=new Random();
                    int nextInt = random.nextInt(10);
                    jedis.setex(key,nextInt*60*1000,jsonString);
                }else {
                    jedis.setex(key,5*60*1000,"empty");
                }
                String script ="if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
                jedis.eval(script, Collections.singletonList(skuLockKey),Collections.singletonList(skuLockValue));
            }else {
                //如果分布式锁访问失败，线程休眠3秒，重新访问
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return goods;
    }

    @Override
    public int updateGoods(Goods goods) {
        int i = goodsMapper.updateById(goods);
        return i;
    }
}
